using Microsoft.Extensions.Logging;
using System.Net;
using System.Net.Sockets;
using Uantek.Device.Communication.Models;

namespace Uantek.Device.Communication.Protocols.Transports
{
    /// <summary>
    /// TCP通信传输实现
    /// </summary>
    public class TcpTransport : BaseCommunicationTransport
    {
        /// <summary>
        /// TCP客户端
        /// </summary>
        private TcpClient? _tcpClient;

        /// <summary>
        /// 网络流
        /// </summary>
        private NetworkStream? _networkStream;

        /// <summary>
        /// 传输类型
        /// </summary>
        public override string TransportType => "TCP";

        /// <summary>
        /// 连接超时时间（毫秒）
        /// </summary>
        public int ConnectTimeout { get; set; } = 5000;

        /// <summary>
        /// 接收超时时间（毫秒）
        /// </summary>
        public int ReceiveTimeout { get; set; } = 5000;

        /// <summary>
        /// 发送超时时间（毫秒）
        /// </summary>
        public int SendTimeout { get; set; } = 5000;

        /// <summary>
        /// 缓冲区大小
        /// </summary>
        public int BufferSize { get; set; } = 4096;

        /// <summary>
        /// 是否启用Keep-Alive
        /// </summary>
        public bool EnableKeepAlive { get; set; } = true;

        /// <summary>
        /// Keep-Alive间隔（秒）
        /// </summary>
        public int KeepAliveInterval { get; set; } = 30;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        public TcpTransport(ILogger<TcpTransport>? logger = null) : base(logger)
        {
        }

        /// <summary>
        /// 连接的具体实现
        /// </summary>
        /// <param name="connectionParameters">连接参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>连接结果</returns>
        protected override async Task<CommunicationResult> ConnectInternalAsync(Dictionary<string, object> connectionParameters, CancellationToken cancellationToken)
        {
            try
            {
                // 获取连接参数
                var host = GetParameter<string>(connectionParameters, "Host", "127.0.0.1");
                var port = GetParameter<int>(connectionParameters, "Port", 502);
                
                // 更新配置参数
                ConnectTimeout = GetParameter<int>(connectionParameters, "ConnectTimeout", ConnectTimeout);
                ReceiveTimeout = GetParameter<int>(connectionParameters, "ReceiveTimeout", ReceiveTimeout);
                SendTimeout = GetParameter<int>(connectionParameters, "SendTimeout", SendTimeout);
                BufferSize = GetParameter<int>(connectionParameters, "BufferSize", BufferSize);
                EnableKeepAlive = GetParameter<bool>(connectionParameters, "EnableKeepAlive", EnableKeepAlive);
                KeepAliveInterval = GetParameter<int>(connectionParameters, "KeepAliveInterval", KeepAliveInterval);

                LogDebug("开始TCP连接，主机: {Host}，端口: {Port}，连接超时: {ConnectTimeout}ms", host, port, ConnectTimeout);

                // 创建TCP客户端
                _tcpClient = new TcpClient();
                
                // 设置连接超时
                _tcpClient.ReceiveTimeout = ReceiveTimeout;
                _tcpClient.SendTimeout = SendTimeout;

                // 连接到服务器
                using var connectCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                connectCts.CancelAfter(ConnectTimeout);

                try
                {
                    await _tcpClient.ConnectAsync(host, port, connectCts.Token);
                }
                catch (OperationCanceledException) when (connectCts.Token.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
                {
                    return CommunicationResult.CreateFailure($"TCP连接超时，主机: {host}，端口: {port}", "ConnectionTimeout");
                }

                if (!_tcpClient.Connected)
                {
                    return CommunicationResult.CreateFailure($"TCP连接失败，主机: {host}，端口: {port}", "ConnectionFailed");
                }

                // 获取网络流
                _networkStream = _tcpClient.GetStream();

                // 配置Keep-Alive
                if (EnableKeepAlive)
                {
                    ConfigureKeepAlive(_tcpClient.Client);
                }

                LogInformation("TCP连接成功，主机: {Host}，端口: {Port}", host, port);
                return CommunicationResult.CreateSuccess("TCP连接成功");
            }
            catch (Exception ex)
            {
                LogError(ex, "TCP连接时发生异常");
                
                // 清理资源
                CleanupConnection();
                
                return CommunicationResult.CreateFailure($"TCP连接异常: {ex.Message}", "ConnectionException", ex);
            }
        }

        /// <summary>
        /// 断开连接的具体实现
        /// </summary>
        /// <returns>断开结果</returns>
        protected override async Task<CommunicationResult> DisconnectInternalAsync()
        {
            try
            {
                LogDebug("开始断开TCP连接");

                CleanupConnection();

                LogInformation("TCP连接断开成功");
                await Task.CompletedTask;
                return CommunicationResult.CreateSuccess("TCP连接断开成功");
            }
            catch (Exception ex)
            {
                LogError(ex, "断开TCP连接时发生异常");
                return CommunicationResult.CreateFailure($"断开TCP连接异常: {ex.Message}", "DisconnectionException", ex);
            }
        }

        /// <summary>
        /// 发送数据的具体实现
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>发送结果</returns>
        protected override CommunicationResult SendDataInternal(byte[] data)
        {
            try
            {
                if (_networkStream == null || !_networkStream.CanWrite)
                {
                    return CommunicationResult.CreateFailure("网络流不可写", "StreamNotWritable");
                }

                LogDebug("发送TCP数据，长度: {Length}，数据: {Data}", data.Length, Convert.ToHexString(data));

                _networkStream.Write(data, 0, data.Length);
                _networkStream.Flush();

                LogDebug("TCP数据发送成功，长度: {Length}", data.Length);
                return CommunicationResult.CreateSuccess("TCP数据发送成功");
            }
            catch (Exception ex)
            {
                LogError(ex, "发送TCP数据时发生异常");
                return CommunicationResult.CreateFailure($"发送TCP数据异常: {ex.Message}", "SendException", ex);
            }
        }

        /// <summary>
        /// 配置参数的具体实现
        /// </summary>
        /// <param name="parameters">参数</param>
        /// <returns>配置结果</returns>
        protected override async Task<CommunicationResult> ConfigureInternalAsync(Dictionary<string, object> parameters)
        {
            try
            {
                LogDebug("开始配置TCP传输参数");

                // 更新配置参数
                ConnectTimeout = GetParameter<int>(parameters, "ConnectTimeout", ConnectTimeout);
                ReceiveTimeout = GetParameter<int>(parameters, "ReceiveTimeout", ReceiveTimeout);
                SendTimeout = GetParameter<int>(parameters, "SendTimeout", SendTimeout);
                BufferSize = GetParameter<int>(parameters, "BufferSize", BufferSize);
                EnableKeepAlive = GetParameter<bool>(parameters, "EnableKeepAlive", EnableKeepAlive);
                KeepAliveInterval = GetParameter<int>(parameters, "KeepAliveInterval", KeepAliveInterval);

                // 如果已连接，更新连接的超时设置
                if (_tcpClient != null && _tcpClient.Connected)
                {
                    _tcpClient.ReceiveTimeout = ReceiveTimeout;
                    _tcpClient.SendTimeout = SendTimeout;

                    if (EnableKeepAlive)
                    {
                        ConfigureKeepAlive(_tcpClient.Client);
                    }
                }

                LogDebug("TCP传输参数配置完成");
                await Task.CompletedTask;
                return CommunicationResult.CreateSuccess("TCP传输参数配置成功");
            }
            catch (Exception ex)
            {
                LogError(ex, "配置TCP传输参数时发生异常");
                return CommunicationResult.CreateFailure($"配置TCP传输参数异常: {ex.Message}", "ConfigurationException", ex);
            }
        }

        /// <summary>
        /// 数据接收循环
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>任务</returns>
        protected override async Task ReceiveDataLoopAsync(CancellationToken cancellationToken)
        {
            var buffer = new byte[BufferSize];

            try
            {
                LogDebug("开始TCP数据接收循环，缓冲区大小: {BufferSize}", BufferSize);

                while (!cancellationToken.IsCancellationRequested && IsConnected && _networkStream != null)
                {
                    try
                    {
                        if (!_networkStream.CanRead)
                        {
                            LogWarning("网络流不可读，退出接收循环");
                            break;
                        }

                        // 检查是否有数据可读
                        if (!_networkStream.DataAvailable)
                        {
                            await Task.Delay(10, cancellationToken);
                            continue;
                        }

                        var bytesRead = await _networkStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                        
                        if (bytesRead > 0)
                        {
                            var data = new byte[bytesRead];
                            Array.Copy(buffer, 0, data, 0, bytesRead);
                            
                            LogDebug("接收到TCP数据，长度: {Length}，数据: {Data}", bytesRead, Convert.ToHexString(data));
                            
                            OnDataReceived(data);
                        }
                        else
                        {
                            LogWarning("TCP连接已关闭，接收到0字节");
                            break;
                        }
                    }
                    catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
                    {
                        LogDebug("TCP数据接收循环被取消");
                        break;
                    }
                    catch (ObjectDisposedException)
                    {
                        LogDebug("TCP客户端已释放，退出接收循环");
                        break;
                    }
                    catch (IOException ex)
                    {
                        LogError(ex, "TCP数据接收时发生IO异常");
                        break;
                    }
                    catch (Exception ex)
                    {
                        LogError(ex, "TCP数据接收时发生异常");
                        await Task.Delay(1000, cancellationToken); // 等待一段时间后重试
                    }
                }

                LogDebug("TCP数据接收循环结束");
            }
            catch (Exception ex)
            {
                LogError(ex, "TCP数据接收循环发生异常");
            }
        }

        /// <summary>
        /// 构建连接信息
        /// </summary>
        /// <param name="connectionParameters">连接参数</param>
        /// <returns>连接信息</returns>
        protected override string BuildConnectionInfo(Dictionary<string, object> connectionParameters)
        {
            var host = GetParameter<string>(connectionParameters, "Host", "127.0.0.1");
            var port = GetParameter<int>(connectionParameters, "Port", 502);
            return $"TCP://{host}:{port}";
        }

        /// <summary>
        /// 释放资源的具体实现
        /// </summary>
        protected override void DisposeInternal()
        {
            CleanupConnection();
        }

        #region 私有方法

        /// <summary>
        /// 清理连接资源
        /// </summary>
        private void CleanupConnection()
        {
            try
            {
                _networkStream?.Close();
                _networkStream?.Dispose();
                _networkStream = null;

                _tcpClient?.Close();
                _tcpClient?.Dispose();
                _tcpClient = null;

                LogDebug("TCP连接资源清理完成");
            }
            catch (Exception ex)
            {
                LogError(ex, "清理TCP连接资源时发生异常");
            }
        }

        /// <summary>
        /// 配置Keep-Alive
        /// </summary>
        /// <param name="socket">套接字</param>
        private void ConfigureKeepAlive(Socket socket)
        {
            try
            {
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                
                // 设置Keep-Alive参数（Windows平台）
                if (OperatingSystem.IsWindows())
                {
                    var keepAliveValues = new byte[12];
                    BitConverter.GetBytes(1).CopyTo(keepAliveValues, 0); // 启用Keep-Alive
                    BitConverter.GetBytes(KeepAliveInterval * 1000).CopyTo(keepAliveValues, 4); // Keep-Alive间隔
                    BitConverter.GetBytes(1000).CopyTo(keepAliveValues, 8); // Keep-Alive重试间隔
                    
                    socket.IOControl(IOControlCode.KeepAliveValues, keepAliveValues, null);
                }
                
                LogDebug("TCP Keep-Alive配置完成，间隔: {Interval}秒", KeepAliveInterval);
            }
            catch (Exception ex)
            {
                LogError(ex, "配置TCP Keep-Alive时发生异常");
            }
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 获取本地端点信息
        /// </summary>
        /// <returns>本地端点</returns>
        public IPEndPoint? GetLocalEndPoint()
        {
            return _tcpClient?.Client?.LocalEndPoint as IPEndPoint;
        }

        /// <summary>
        /// 获取远程端点信息
        /// </summary>
        /// <returns>远程端点</returns>
        public IPEndPoint? GetRemoteEndPoint()
        {
            return _tcpClient?.Client?.RemoteEndPoint as IPEndPoint;
        }

        /// <summary>
        /// 检查连接状态
        /// </summary>
        /// <returns>连接是否有效</returns>
        public bool IsConnectionHealthy()
        {
            try
            {
                if (_tcpClient == null || !_tcpClient.Connected)
                    return false;

                // 使用Socket.Poll检查连接状态
                var socket = _tcpClient.Client;
                return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取连接统计信息
        /// </summary>
        /// <returns>统计信息</returns>
        public Dictionary<string, object> GetConnectionStats()
        {
            var stats = new Dictionary<string, object>
            {
                ["TransportType"] = TransportType,
                ["IsConnected"] = IsConnected,
                ["IsHealthy"] = IsConnectionHealthy(),
                ["ConnectTimeout"] = ConnectTimeout,
                ["ReceiveTimeout"] = ReceiveTimeout,
                ["SendTimeout"] = SendTimeout,
                ["BufferSize"] = BufferSize,
                ["EnableKeepAlive"] = EnableKeepAlive,
                ["KeepAliveInterval"] = KeepAliveInterval
            };

            var localEndPoint = GetLocalEndPoint();
            var remoteEndPoint = GetRemoteEndPoint();

            if (localEndPoint != null)
            {
                stats["LocalEndPoint"] = localEndPoint.ToString();
            }

            if (remoteEndPoint != null)
            {
                stats["RemoteEndPoint"] = remoteEndPoint.ToString();
            }

            return stats;
        }

        #endregion
    }
}